﻿/*
 * ArchiveFactory.h
 *
 */
#ifndef __GDK_ARCHIVEFACTORY_H__
#define __GDK_ARCHIVEFACTORY_H__

#include <gdk/core/Types.h>
#include <gdk/core/Archive.h>


namespace gdk
{


	///////////////////////////////////////////////////////////////
	class GDK_CORE_EXPORT ArchiveFactory
	{
	private:
		String				_archiveType;
		ArchiveFactory*		_next;

	public:
		ArchiveFactory(const String& archiveType);

	public:
		__INLINE__ const String& getArchiveType(void) const { return _archiveType; }

	public:
		virtual Archive::Handle open(const String &url) =0;

	public:
		static bool setUpArchiveFactory(ArchiveFactory *archiveFactory);
		static bool tearDownArchiveFactory(ArchiveFactory *archiveFactory);
		static ArchiveFactory* getArchiveFactory(const String &archiveType);

		/*
			file://c:/a.txt
				or file://a.txt
				or ./a.txt or ./a.txt?position=8
			http://192.168.0.1/a.txt
				or http://192.168.0.1/a.txt?position=8
			ftp://192.168.0.1/a.txt
				or ftp://192.168.0.1/a.txt?position=8
			7zip://a.txt<<file://a.7z
				or 7zip://a.txt<<7zip://b.7z<<file://c.7z
				or 7zip://a.txt<<memory://<<http://192.168.0.1/a.7z
				or 7zip://a.txt?position=8<<file://a.7z
			memory://
				or memory://<<file://a.txt
				or memory://?position=8<<file://a.txt
				or memory://<<file://a.txt?position=8
		*/
		static Archive::Handle openArchive(const String &url);

		//分析url
		static void parseUrl(const String &url,String &fileName,String &args);
	};


#define IMPLEMENT_ARCHIVEFACTORY(Class) \
	static Class g_##Class;\
	static void tearDownArchiveFactory_##Class(void)\
	{\
		gdk::ArchiveFactory::tearDownArchiveFactory(&g_##Class);\
	}\
	static bool setUpArchiveFactory_##Class(void)\
	{\
		gdk::ArchiveFactory::setUpArchiveFactory(&g_##Class);\
		::atexit(tearDownArchiveFactory_##Class);\
		return true;\
	}\
	bool const g_##Class##_Flag = setUpArchiveFactory_##Class();

#define DECLARE_ARCHIVEFACTORY(Class) \
	extern bool const g_##Class##_Flag;\
	static bool const g_##Class##_flag_ = (gdk::nothing(&g_##Class##_flag_), g_##Class##_Flag);\
	/*DECLARE_FUTILITY_VARIABLE(static const bool, g_##Class##_Flag);*/




}//namespace gdk


#endif /*__GDK_ARCHIVEFACTORY_H__*/
